home *** CD-ROM | disk | FTP | other *** search
/ The Utilities Experience / The Utilities Experience - Volume 1.iso / software / misc / o-z / x-windows / mesa-amiwin / src / lines.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-11-30  |  21.7 KB  |  853 lines

  1. /* lines.c */
  2.  
  3. /*
  4.  * Mesa 3-D graphics library
  5.  * Version:  1.2
  6.  * Copyright (C) 1995  Brian Paul  (brianp@ssec.wisc.edu)
  7.  *
  8.  * This library is free software; you can redistribute it and/or
  9.  * modify it under the terms of the GNU Library General Public
  10.  * License as published by the Free Software Foundation; either
  11.  * version 2 of the License, or (at your option) any later version.
  12.  *
  13.  * This library is distributed in the hope that it will be useful,
  14.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  16.  * Library General Public License for more details.
  17.  *
  18.  * You should have received a copy of the GNU Library General Public
  19.  * License along with this library; if not, write to the Free
  20.  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  21.  */
  22.  
  23.  
  24. /*
  25. $Id: lines.c,v 1.27 1995/10/23 21:28:30 brianp Exp $
  26.  
  27. $Log: lines.c,v $
  28.  * Revision 1.27  1995/10/23  21:28:30  brianp
  29.  * use new gl_interpolate_4ub function
  30.  *
  31.  * Revision 1.26  1995/10/17  21:40:58  brianp
  32.  * removed simple_ci/rgba_line() functions because of new device driver
  33.  *
  34.  * Revision 1.25  1995/09/21  14:07:29  brianp
  35.  * more new DD prototyping
  36.  *
  37.  * Revision 1.24  1995/09/20  18:20:39  brianp
  38.  * prototype device driver changes described
  39.  *
  40.  * Revision 1.23  1995/09/13  14:49:34  brianp
  41.  * use CC.NewState convention
  42.  * replaced VB.Vs and VB.Vt with VB.TexCoord
  43.  *
  44.  * Revision 1.22  1995/07/25  18:36:32  brianp
  45.  * convert window coords from floats to ints by rounding, not truncating
  46.  *
  47.  * Revision 1.21  1995/07/15  14:03:49  brianp
  48.  * added texture mapped lines
  49.  *
  50.  * Revision 1.20  1995/07/07  12:41:51  brianp
  51.  * use CLAMP macro in glLineStipple, upper limit being 256, not 255
  52.  *
  53.  * Revision 1.19  1995/06/20  16:21:34  brianp
  54.  * do float-to-int depth scaling here instead of in draw.c
  55.  *
  56.  * Revision 1.18  1995/06/12  15:39:09  brianp
  57.  * changed color arrays to GLubyte
  58.  * implement GL_LINE_RESET_TOKEN for feedback
  59.  * new interpolation functions
  60.  *
  61.  * Revision 1.17  1995/06/07  14:47:04  brianp
  62.  * faster width=2 lines
  63.  *
  64.  * Revision 1.16  1995/06/05  20:27:09  brianp
  65.  * removed PB.clipflag stuff
  66.  *
  67.  * Revision 1.15  1995/05/22  21:02:41  brianp
  68.  * Release 1.2
  69.  *
  70.  * Revision 1.14  1995/05/12  19:26:43  brianp
  71.  * replaced CC.Mode!=0 with INSIDE_BEGIN_END
  72.  *
  73.  * Revision 1.13  1995/05/12  16:26:50  brianp
  74.  * let PB do clipping of pixels for lines wider than 1
  75.  *
  76.  * Revision 1.12  1995/04/18  15:48:23  brianp
  77.  * fixed assignment of NULL to function pointers to prevent warnings on Suns
  78.  *
  79.  * Revision 1.11  1995/04/12  15:36:15  brianp
  80.  * updated to use DD.draw_* function pointers
  81.  *
  82.  * Revision 1.10  1995/03/27  20:31:53  brianp
  83.  * new Texture.Enabled scheme
  84.  *
  85.  * Revision 1.9  1995/03/24  15:33:25  brianp
  86.  * introduced VB
  87.  *
  88.  * Revision 1.8  1995/03/07  14:20:50  brianp
  89.  * updated for new XSetForeground/GC scheme
  90.  *
  91.  * Revision 1.7  1995/03/04  19:29:44  brianp
  92.  * 1.1 beta revision
  93.  *
  94.  * Revision 1.6  1995/03/04  19:16:57  brianp
  95.  * added width clamp
  96.  *
  97.  * Revision 1.5  1995/03/02  19:18:20  brianp
  98.  * new RasterMask logic
  99.  *
  100.  * Revision 1.4  1995/02/27  22:48:54  brianp
  101.  * modified for PB
  102.  *
  103.  * Revision 1.3  1995/02/27  15:08:08  brianp
  104.  * added Vcolor/Vindex scheme
  105.  *
  106.  * Revision 1.2  1995/02/24  15:15:53  brianp
  107.  * changed && to & in gl_set_line_func
  108.  *
  109.  * Revision 1.1  1995/02/24  14:23:09  brianp
  110.  * Initial revision
  111.  *
  112.  */
  113.  
  114.  
  115. #include "bresenhm.h"
  116. #include "context.h"
  117. #include "dd.h"
  118. #include "feedback.h"
  119. #include "interp.h"
  120. #include "list.h"
  121. #include "macros.h"
  122. #include "pb.h"
  123. #include "vb.h"
  124.  
  125.  
  126. #ifndef NULL
  127. #  define NULL 0
  128. #endif
  129.  
  130.  
  131. void glLineWidth( GLfloat width )
  132. {
  133.    if (CC.CompileFlag) {
  134.       gl_save_linewidth( width );
  135.    }
  136.    if (CC.ExecuteFlag) {
  137.       if (width<=0.0) {
  138.      gl_error( GL_INVALID_VALUE, "glLineWidth" );
  139.      return;
  140.       }
  141.       if (INSIDE_BEGIN_END) {
  142.      gl_error( GL_INVALID_OPERATION, "glLineWidth" );
  143.      return;
  144.       }
  145.  
  146.       CC.Line.Width = width;
  147.       CC.NewState = GL_TRUE;
  148.    }
  149. }
  150.  
  151.  
  152.  
  153. void glLineStipple( GLint factor, GLushort pattern )
  154. {
  155.    if (CC.CompileFlag) {
  156.       gl_save_linestipple( factor, pattern );
  157.    }
  158.    if (CC.ExecuteFlag) {
  159.       if (INSIDE_BEGIN_END) {
  160.      gl_error( GL_INVALID_OPERATION, "glLineStipple" );
  161.      return;
  162.       }
  163.  
  164.       CC.Line.StippleFactor = CLAMP( factor, 1, 256 );
  165.       CC.Line.StipplePattern = pattern;
  166.    }
  167. }
  168.  
  169.  
  170.  
  171. /**********************************************************************/
  172. /*****                    Rasterization                           *****/
  173. /**********************************************************************/
  174.  
  175.  
  176. /*
  177.  * There are 4 pairs (RGBA, CI) of line drawing functions:
  178.  *   1. simple:  width=1 and no special rasterization functions (fastest)
  179.  *   2. flat:  width=1, non-stippled, flat-shaded, any raster operations
  180.  *   3. smooth:  width=1, non-stippled, smooth-shaded, any raster operations
  181.  *   4. general:  any other kind of line (slowest)
  182.  */
  183.  
  184.  
  185. /*
  186.  * All line drawing functions have the same arguments:
  187.  * v1, v2 - indexes of first and second endpoints into vertex buffer arrays
  188.  * pv     - provoking vertex: which vertex color/index to use for flat shading.
  189.  */
  190.  
  191.  
  192.  
  193. static void feedback_line( GLuint v1, GLuint v2, GLuint pv )
  194. {
  195.    GLfloat x1, y1, z1, w1;
  196.    GLfloat x2, y2, z2, w2;
  197.    GLfloat tex1[4], tex2[4];  /* texture coord */
  198.  
  199.    x1 = VB.Win[v1][0];
  200.    y1 = VB.Win[v1][1];
  201.    z1 = VB.Win[v1][2];
  202.    w1 = VB.Clip[v1][3];
  203.  
  204.    x2 = VB.Win[v2][0];
  205.    y2 = VB.Win[v2][1];
  206.    z2 = VB.Win[v2][2];
  207.    w2 = VB.Clip[v2][3];
  208.  
  209.    if (CC.StippleCounter==0) {
  210.       APPEND_TOKEN( (GLfloat) GL_LINE_RESET_TOKEN );
  211.    }
  212.    else {
  213.       APPEND_TOKEN( (GLfloat) GL_LINE_TOKEN );
  214.    }
  215.    if (CC.Light.ShadeModel==GL_FLAT) {
  216.       gl_feedback_vertex( x1,y1,z1,w1, VB.Color[pv], VB.Index[pv], tex1 );
  217.       gl_feedback_vertex( x2,y2,z2,w2, VB.Color[pv], VB.Index[pv], tex2 );
  218.    }
  219.    else {
  220.       gl_feedback_vertex( x1,y1,z1,w1, VB.Color[v1], VB.Index[v1], tex1 );
  221.       gl_feedback_vertex( x2,y2,z2,w2, VB.Color[v2], VB.Index[v2], tex2 );
  222.    }
  223.    CC.StippleCounter++;
  224. }
  225.  
  226.  
  227.  
  228. static void select_line( GLuint v1, GLuint v2, GLuint pv )
  229. {
  230.    GLfloat z1 = VB.Win[v1][2];
  231.    GLfloat z2 = VB.Win[v2][2];
  232.  
  233.    CC.HitFlag = GL_TRUE;
  234.    if (z1 < CC.HitMinZ) {
  235.       CC.HitMinZ = z1;
  236.    }
  237.    if (z1 > CC.HitMaxZ) {
  238.       CC.HitMaxZ = z1;
  239.    }
  240.    if (z2 < CC.HitMinZ) {
  241.       CC.HitMinZ = z2;
  242.    }
  243.    if (z2 > CC.HitMaxZ) {
  244.       CC.HitMaxZ = z2;
  245.    }
  246. }
  247.  
  248.  
  249.  
  250. #if MAX_WIDTH > MAX_HEIGHT
  251. #  define MAXPOINTS MAX_WIDTH
  252. #else
  253. #  define MAXPOINTS MAX_HEIGHT
  254. #endif
  255.  
  256.  
  257. /*
  258.  * Flat shaded, width=1, non-stippled, color index line.
  259.  */
  260. static void flat_ci_line( GLuint v1, GLuint v2, GLuint pv )
  261. {
  262.    GLint x1 = (GLint) (VB.Win[v1][0] + 0.5F);
  263.    GLint y1 = (GLint) (VB.Win[v1][1] + 0.5F);
  264.    GLint x2 = (GLint) (VB.Win[v2][0] + 0.5F);
  265.    GLint y2 = (GLint) (VB.Win[v2][1] + 0.5F);
  266.    GLuint index = (GLuint) VB.Index[pv];
  267.    GLuint n;
  268.  
  269.    PB_SET_INDEX( index );
  270.  
  271.    /* compute pixel locations */
  272.    n = gl_bresenham( x1, y1, x2, y2, PB.x+PB.count, PB.y+PB.count );
  273.  
  274.    /* interpolate z values */
  275.    if (CC.Depth.Test) {
  276.       GLint z1 = (GLint) (VB.Win[v1][2] * DEPTH_SCALE);
  277.       GLint z2 = (GLint) (VB.Win[v2][2] * DEPTH_SCALE);
  278.       gl_interpolate_i( n, z1, z2, PB.z+PB.count );
  279.    }
  280.  
  281.    PB.count += n;
  282.    PB_CHECK_FLUSH
  283. }
  284.  
  285.  
  286. /*
  287.  * Flat-shaded, width=1, non-stippled, rgba line.
  288.  */
  289. static void flat_rgba_line( GLuint v1, GLuint v2, GLuint pv )
  290. {
  291.    GLint x1 = (GLint) (VB.Win[v1][0] + 0.5F);
  292.    GLint y1 = (GLint) (VB.Win[v1][1] + 0.5F);
  293.    GLint x2 = (GLint) (VB.Win[v2][0] + 0.5F);
  294.    GLint y2 = (GLint) (VB.Win[v2][1] + 0.5F);
  295.    GLuint n;
  296.  
  297.    PB_SET_COLOR( VB.Color[pv] );
  298.  
  299.    /* compute pixel locations */
  300.    n = gl_bresenham( x1, y1, x2, y2, PB.x+PB.count, PB.y+PB.count );
  301.  
  302.    /* interpolate z values */
  303.    if (CC.Depth.Test) {
  304.       GLint z1 = (GLint) (VB.Win[v1][2] * DEPTH_SCALE);
  305.       GLint z2 = (GLint) (VB.Win[v2][2] * DEPTH_SCALE);
  306.       gl_interpolate_i( n, z1, z2, PB.z+PB.count );
  307.    }
  308.  
  309.    PB.count += n;
  310.    PB_CHECK_FLUSH
  311. }
  312.  
  313.  
  314.  
  315. /*
  316.  * Smooth-shaded, width=1, non-stippled, color index line.
  317.  */
  318. static void smooth_ci_line( GLuint v1, GLuint v2, GLuint pv )
  319. {
  320.    GLint x1 = (GLint) (VB.Win[v1][0] + 0.5F);
  321.    GLint y1 = (GLint) (VB.Win[v1][1] + 0.5F);
  322.    GLint x2 = (GLint) (VB.Win[v2][0] + 0.5F);
  323.    GLint y2 = (GLint) (VB.Win[v2][1] + 0.5F);
  324.    GLuint n;
  325.  
  326.    /* compute pixel locations */
  327.    n = gl_bresenham( x1, y1, x2, y2, PB.x+PB.count, PB.y+PB.count );
  328.  
  329.    /* interpolate z values */
  330.    if (CC.Depth.Test) {
  331.       GLint z1 = (GLint) (VB.Win[v1][2] * DEPTH_SCALE);
  332.       GLint z2 = (GLint) (VB.Win[v2][2] * DEPTH_SCALE);
  333.       gl_interpolate_i( n, z1, z2, PB.z+PB.count );
  334.    }
  335.  
  336.    /* interpolate index */
  337.    gl_interpolate_i( n, (GLint) VB.Index[v1], (GLint) VB.Index[v2],
  338.                 (GLint *) PB.i+PB.count );
  339.  
  340.    PB.count += n;
  341.    PB_CHECK_FLUSH
  342. }
  343.  
  344.  
  345. /*
  346.  * Smooth-shaded, width=1, non-stippled, RGBA line.
  347.  */
  348. static void smooth_rgba_line( GLuint v1, GLuint v2, GLuint pv )
  349. {
  350.    GLint x1 = (GLint) (VB.Win[v1][0] + 0.5F);
  351.    GLint y1 = (GLint) (VB.Win[v1][1] + 0.5F);
  352.    GLint x2 = (GLint) (VB.Win[v2][0] + 0.5F);
  353.    GLint y2 = (GLint) (VB.Win[v2][1] + 0.5F);
  354.    GLuint i, n;
  355.  
  356.    /* compute pixel locations */
  357.    n = gl_bresenham( x1, y1, x2, y2, PB.x+PB.count, PB.y+PB.count );
  358.  
  359.    /* interpolate z values */
  360.    if (CC.Depth.Test) {
  361.       GLint z1 = (GLint) (VB.Win[v1][2] * DEPTH_SCALE);
  362.       GLint z2 = (GLint) (VB.Win[v2][2] * DEPTH_SCALE);
  363.       gl_interpolate_i( n, z1, z2, PB.z+PB.count );
  364.    }
  365.  
  366.    /* interpolate color */
  367.    gl_interpolate_4ub( n,
  368.               (GLint) (VB.Color[v1][0] * CC.RedScale),
  369.               (GLint) (VB.Color[v2][0] * CC.RedScale ),
  370.               PB.r+PB.count,
  371.               (GLint) (VB.Color[v1][1] * CC.GreenScale),
  372.               (GLint) (VB.Color[v2][1] * CC.GreenScale ),
  373.               PB.g+PB.count,
  374.               (GLint) (VB.Color[v1][2] * CC.BlueScale),
  375.               (GLint) (VB.Color[v2][2] * CC.BlueScale ),
  376.               PB.b+PB.count,
  377.               (GLint) (VB.Color[v1][3] * CC.AlphaScale),
  378.               (GLint) (VB.Color[v2][3] * CC.AlphaScale ),
  379.               PB.a+PB.count );
  380.  
  381.    PB.count += n;
  382.    PB_CHECK_FLUSH
  383. }
  384.  
  385.  
  386.  
  387. /*
  388.  * General CI line:  any width, smooth or flat, stippled, any raster ops.
  389.  */
  390. static void general_ci_line( GLuint v1, GLuint v2, GLuint pv )
  391. {
  392.    GLint x1, y1, x2, y2;
  393.    GLint x[MAXPOINTS], y[MAXPOINTS], z[MAXPOINTS];
  394.    GLubyte mask[MAXPOINTS];
  395.    GLuint index[MAXPOINTS];
  396.    GLuint i, n;
  397.    GLint dx, dy;
  398.  
  399.    x1 = (GLint) (VB.Win[v1][0] + 0.5F);
  400.    y1 = (GLint) (VB.Win[v1][1] + 0.5F);
  401.    x2 = (GLint) (VB.Win[v2][0] + 0.5F);
  402.    y2 = (GLint) (VB.Win[v2][1] + 0.5F);
  403.  
  404.    /* compute pixel locations */
  405.    if (CC.Line.StippleFlag) {
  406.       n = gl_stippled_bresenham( x1, y1, x2, y2, x, y, mask );
  407.    }
  408.    else {
  409.       n = gl_bresenham( x1, y1, x2, y2, x, y );
  410.       for (i=0;i<n;i++) {
  411.      mask[i] = 1;
  412.       }
  413.    }
  414.  
  415.    if (CC.Depth.Test) {
  416.       /* interpolate z */
  417.       GLint z1 = (GLint) (VB.Win[v1][2] * DEPTH_SCALE);
  418.       GLint z2 = (GLint) (VB.Win[v2][2] * DEPTH_SCALE);
  419.       GL_INTERPOLATE_I( n, z1, z2, z );
  420.    }
  421.  
  422.    if (CC.Light.ShadeModel==GL_FLAT) {
  423.       for (i=0;i<n;i++) {
  424.      index[i] = (GLuint) VB.Index[pv];
  425.       }
  426.    }
  427.    else {
  428.       /* interpolate index */
  429.       gl_interpolate_i( n, (GLint) VB.Index[v1], (GLint) VB.Index[v2],
  430.                 (GLint *) index );
  431.    }
  432.  
  433.    /* compute delta x and delta y */
  434.    if (x1>x2) {
  435.       dx = x1 - x2;
  436.    }
  437.    else {
  438.       dx = x2 - x1;
  439.    }
  440.    if (y1>y2) {
  441.       dy = y1 - y2;
  442.    }
  443.    else {
  444.       dy = y2 - y1;
  445.    }
  446.  
  447.  
  448.    /* render */
  449.    if (CC.Line.Width==2.0F) {
  450.       /* special case, easy to optimize */
  451.       if (dx>dy) {
  452.      /* X-major: duplicate pixels in Y direction */
  453.      for (i=0;i<n;i++) {
  454.         if (mask[i]) {
  455.            PB_WRITE_CI_PIXEL( x[i], y[i]-1, z[i], index[i] );
  456.            PB_WRITE_CI_PIXEL( x[i], y[i], z[i], index[i] );
  457.         }
  458.      }
  459.       }
  460.       else {
  461.      /* Y-major: duplicate pixels in X direction */
  462.      for (i=0;i<n;i++) {
  463.         if (mask[i]) {
  464.            PB_WRITE_CI_PIXEL( x[i]-1, y[i], z[i], index[i] );
  465.            PB_WRITE_CI_PIXEL( x[i], y[i], z[i], index[i] );
  466.         }
  467.      }
  468.       }
  469.       PB_CHECK_FLUSH
  470.    }
  471.    else {
  472.       GLint width, w0, w1;
  473.       width = (GLint) CLAMP( CC.Line.Width, MIN_LINE_WIDTH, MAX_LINE_WIDTH );
  474.       w0 = -width / 2;
  475.       w1 = w0 + width - 1;
  476.  
  477.       if (dx>dy) {
  478.      /* X-major: duplicate pixels in Y direction */
  479.      for (i=0;i<n;i++) {
  480.         if (mask[i]) {
  481.            GLint yy;
  482.            GLint y0 = y[i] + w0;
  483.            GLint y1 = y[i] + w1;
  484.            for (yy=y0;yy<=y1;yy++) {
  485.           PB_WRITE_CI_PIXEL( x[i], yy, z[i], index[i] );
  486.            }
  487.            PB_CHECK_FLUSH
  488.         }
  489.      }
  490.       }
  491.       else {
  492.      /* Y-major: duplicate pixels in X direction */
  493.      for (i=0;i<n;i++) {
  494.         if (mask[i]) {
  495.            GLint xx;
  496.            GLint x0 = x[i] + w0;
  497.            GLint x1 = x[i] + w1;
  498.            for (xx=x0;xx<=x1;xx++) {
  499.           PB_WRITE_CI_PIXEL( xx, y[i], z[i], index[i] );
  500.            }
  501.            PB_CHECK_FLUSH
  502.         }
  503.      }
  504.       }
  505.    }
  506. }
  507.  
  508.  
  509. /*
  510.  * General RGBA line:  any width, smooth or flat, stippled, any raster ops.
  511.  */
  512. static void general_rgba_line( GLuint v1, GLuint v2, GLuint pv )
  513. {
  514.    GLint x1, y1, x2, y2;
  515.    GLint x[MAXPOINTS], y[MAXPOINTS], z[MAXPOINTS];
  516.    GLubyte mask[MAXPOINTS];
  517.    GLubyte red[MAXPOINTS], green[MAXPOINTS], blue[MAXPOINTS], alpha[MAXPOINTS];
  518.    GLuint i, n;
  519.    GLint dx, dy;
  520.  
  521.    x1 = (GLint) (VB.Win[v1][0] + 0.5F);
  522.    y1 = (GLint) (VB.Win[v1][1] + 0.5F);
  523.    x2 = (GLint) (VB.Win[v2][0] + 0.5F);
  524.    y2 = (GLint) (VB.Win[v2][1] + 0.5F);
  525.  
  526.    /* compute the line */
  527.    if (CC.Line.StippleFlag) {
  528.       n = gl_stippled_bresenham( x1, y1, x2, y2, x, y, mask );
  529.    }
  530.    else {
  531.       n = gl_bresenham( x1, y1, x2, y2, x, y );
  532.       for (i=0;i<n;i++) {
  533.      mask[i] = 1;
  534.       }
  535.    }
  536.  
  537.    if (CC.Depth.Test) {
  538.       GLint z1 = (GLint) (VB.Win[v1][2] * DEPTH_SCALE);
  539.       GLint z2 = (GLint) (VB.Win[v2][2] * DEPTH_SCALE);
  540.       GL_INTERPOLATE_I( n, z1, z2, z );
  541.    }
  542.  
  543.    if (CC.Light.ShadeModel==GL_FLAT) {
  544.       GLint r, g, b, a;
  545.       r = (GLint) (VB.Color[pv][0] * CC.RedScale);
  546.       g = (GLint) (VB.Color[pv][1] * CC.GreenScale);
  547.       b = (GLint) (VB.Color[pv][2] * CC.BlueScale);
  548.       a = (GLint) (VB.Color[pv][3] * CC.AlphaScale);
  549.       for (i=0;i<n;i++) {
  550.      red[i]   = r;
  551.      green[i] = g;
  552.      blue[i]  = b;
  553.      alpha[i] = a;
  554.       }
  555.    }
  556.    else {
  557.       /* interpolate color */
  558.       gl_interpolate_4ub( n,
  559.                           (GLint) (VB.Color[v1][0] * CC.RedScale),
  560.                           (GLint) (VB.Color[v2][0] * CC.RedScale),
  561.                           red,
  562.                           (GLint) (VB.Color[v1][1] * CC.GreenScale),
  563.                           (GLint) (VB.Color[v2][1] * CC.GreenScale),
  564.                           green,
  565.                           (GLint) (VB.Color[v1][2] * CC.BlueScale),
  566.                           (GLint) (VB.Color[v2][2] * CC.BlueScale),
  567.                           blue,
  568.                           (GLint) (VB.Color[v1][3] * CC.AlphaScale),
  569.                           (GLint) (VB.Color[v2][3] * CC.AlphaScale),
  570.                           alpha );
  571.    }
  572.  
  573.    /* compute delta x and delta y */
  574.    if (x1>x2) {
  575.       dx = x1 - x2;
  576.    }
  577.    else {
  578.       dx = x2 - x1;
  579.    }
  580.    if (y1>y2) {
  581.       dy = y1 - y2;
  582.    }
  583.    else {
  584.       dy = y2 - y1;
  585.    }
  586.  
  587.    /* render */
  588.    if (CC.Line.Width==2.0F) {
  589.       /* special case, easy to optimize */
  590.       if (dx>dy) {
  591.      /* X-major: duplicate pixels in Y direction */
  592.      for (i=0;i<n;i++) {
  593.         if (mask[i]) {
  594.            PB_WRITE_RGBA_PIXEL( x[i], y[i]-1, z[i],
  595.                     red[i], green[i], blue[i], alpha[i] );
  596.            PB_WRITE_RGBA_PIXEL( x[i], y[i], z[i],
  597.                     red[i], green[i], blue[i], alpha[i] );
  598.         }
  599.      }
  600.       }
  601.       else {
  602.      /* Y-major: duplicate pixels in X direction */
  603.      for (i=0;i<n;i++) {
  604.         if (mask[i]) {
  605.            PB_WRITE_RGBA_PIXEL( x[i]-1, y[i], z[i],
  606.                     red[i], green[i], blue[i], alpha[i] );
  607.            PB_WRITE_RGBA_PIXEL( x[i], y[i], z[i],
  608.                     red[i], green[i], blue[i], alpha[i] );
  609.         }
  610.      }
  611.       }
  612.       PB_CHECK_FLUSH
  613.    }
  614.    else {
  615.       GLint width, w0, w1;
  616.       width = (GLint) CLAMP( CC.Line.Width, MIN_LINE_WIDTH, MAX_LINE_WIDTH );
  617.       w0 = -width / 2;
  618.       w1 = w0 + width - 1;
  619.  
  620.       if (dx>dy) {
  621.      /* X-major: duplicate pixels in Y direction */
  622.      for (i=0;i<n;i++) {
  623.         if (mask[i]) {
  624.            GLint yy;
  625.            GLint y0 = y[i] + w0;
  626.            GLint y1 = y[i] + w1;
  627.            for (yy=y0;yy<=y1;yy++) {
  628.           PB_WRITE_RGBA_PIXEL( x[i], yy, z[i],
  629.                        red[i], green[i], blue[i], alpha[i] );
  630.            }
  631.            PB_CHECK_FLUSH
  632.         }
  633.      }
  634.       }
  635.       else {
  636.      /* Y-major: duplicate pixels in X direction */
  637.      for (i=0;i<n;i++) {
  638.         if (mask[i]) {
  639.            GLint xx;
  640.            GLint x0 = x[i] + w0;
  641.            GLint x1 = x[i] + w1;
  642.            for (xx=x0;xx<=x1;xx++) {
  643.           PB_WRITE_RGBA_PIXEL( xx, y[i], z[i],
  644.                        red[i], green[i], blue[i], alpha[i] );
  645.            }
  646.            PB_CHECK_FLUSH
  647.         }
  648.      }
  649.       }
  650.    }
  651. }
  652.  
  653.  
  654.  
  655. /*
  656.  * Textured RGBA line:  any width, smooth or flat, stippled, any raster ops
  657.  * with texturing.
  658.  */
  659. static void textured_rgba_line( GLuint v1, GLuint v2, GLuint pv )
  660. {
  661.    GLint x1, y1, x2, y2;
  662.    GLint x[MAXPOINTS], y[MAXPOINTS], z[MAXPOINTS];
  663.    GLubyte mask[MAXPOINTS];
  664.    GLubyte red[MAXPOINTS], green[MAXPOINTS], blue[MAXPOINTS], alpha[MAXPOINTS];
  665.    GLfloat s[MAXPOINTS], t[MAXPOINTS];
  666.    GLuint i, n;
  667.    GLint dx, dy;
  668.  
  669.    x1 = (GLint) (VB.Win[v1][0] + 0.5F);
  670.    y1 = (GLint) (VB.Win[v1][1] + 0.5F);
  671.    x2 = (GLint) (VB.Win[v2][0] + 0.5F);
  672.    y2 = (GLint) (VB.Win[v2][1] + 0.5F);
  673.  
  674.    /* compute the line */
  675.    if (CC.Line.StippleFlag) {
  676.       n = gl_stippled_bresenham( x1, y1, x2, y2, x, y, mask );
  677.    }
  678.    else {
  679.       n = gl_bresenham( x1, y1, x2, y2, x, y );
  680.       for (i=0;i<n;i++) {
  681.      mask[i] = 1;
  682.       }
  683.    }
  684.  
  685.    if (CC.Depth.Test) {
  686.       GLint z1 = (GLint) (VB.Win[v1][2] * DEPTH_SCALE);
  687.       GLint z2 = (GLint) (VB.Win[v2][2] * DEPTH_SCALE);
  688.       GL_INTERPOLATE_I( n, z1, z2, z );
  689.    }
  690.  
  691.    if (CC.Light.ShadeModel==GL_FLAT) {
  692.       GLint r, g, b, a;
  693.       r = (GLint) (VB.Color[pv][0] * CC.RedScale);
  694.       g = (GLint) (VB.Color[pv][1] * CC.GreenScale);
  695.       b = (GLint) (VB.Color[pv][2] * CC.BlueScale);
  696.       a = (GLint) (VB.Color[pv][3] * CC.AlphaScale);
  697.       for (i=0;i<n;i++) {
  698.      red[i]   = r;
  699.      green[i] = g;
  700.      blue[i]  = b;
  701.      alpha[i] = a;
  702.       }
  703.    }
  704.    else {
  705.       /* interpolate color */
  706.       gl_interpolate_4ub( n,
  707.                           (GLint) (VB.Color[v1][0] * CC.RedScale),
  708.                           (GLint) (VB.Color[v2][0] * CC.RedScale),
  709.                           red,
  710.                           (GLint) (VB.Color[v1][1] * CC.GreenScale),
  711.                           (GLint) (VB.Color[v2][1] * CC.GreenScale),
  712.                           green,
  713.                           (GLint) (VB.Color[v1][2] * CC.BlueScale),
  714.                           (GLint) (VB.Color[v2][2] * CC.BlueScale),
  715.                           blue,
  716.                           (GLint) (VB.Color[v1][3] * CC.AlphaScale),
  717.                           (GLint) (VB.Color[v2][3] * CC.AlphaScale),
  718.                           alpha );
  719.    }
  720.  
  721.    /* interpolate texture coordinates */
  722.    gl_interp_texcoords( n, VB.Eye[v1][2], VB.Eye[v2][2],
  723.                 VB.Win[v1][2] * MAX_DEPTH, VB.Win[v2][2] * MAX_DEPTH,
  724.                 VB.TexCoord[v1][0], VB.TexCoord[v2][0],
  725.                         VB.TexCoord[v1][1], VB.TexCoord[v2][1],
  726.                 s, t, NULL );
  727.  
  728.  
  729.    /* compute delta x and delta y */
  730.    if (x1>x2) {
  731.       dx = x1 - x2;
  732.    }
  733.    else {
  734.       dx = x2 - x1;
  735.    }
  736.    if (y1>y2) {
  737.       dy = y1 - y2;
  738.    }
  739.    else {
  740.       dy = y2 - y1;
  741.    }
  742.  
  743.    /* render */
  744.    if (CC.Line.Width==2.0F) {
  745.       /* special case, easy to optimize */
  746.       if (dx>dy) {
  747.      /* X-major: duplicate pixels in Y direction */
  748.      for (i=0;i<n;i++) {
  749.         if (mask[i]) {
  750.            PB_WRITE_TEX_PIXEL( x[i], y[i]-1, z[i],
  751.               red[i], green[i], blue[i], alpha[i], s[i], t[i] );
  752.            PB_WRITE_TEX_PIXEL( x[i], y[i], z[i],
  753.               red[i], green[i], blue[i], alpha[i], s[i], t[i] );
  754.         }
  755.      }
  756.       }
  757.       else {
  758.      /* Y-major: duplicate pixels in X direction */
  759.      for (i=0;i<n;i++) {
  760.         if (mask[i]) {
  761.            PB_WRITE_TEX_PIXEL( x[i]-1, y[i], z[i],
  762.               red[i], green[i], blue[i], alpha[i], s[i], t[i] );
  763.            PB_WRITE_TEX_PIXEL( x[i], y[i], z[i],
  764.               red[i], green[i], blue[i], alpha[i], s[i], t[i] );
  765.         }
  766.      }
  767.       }
  768.       PB_CHECK_FLUSH
  769.    }
  770.    else {
  771.       GLint width, w0, w1;
  772.       width = (GLint) CLAMP( CC.Line.Width, MIN_LINE_WIDTH, MAX_LINE_WIDTH );
  773.       w0 = -width / 2;
  774.       w1 = w0 + width - 1;
  775.  
  776.       if (dx>dy) {
  777.      /* X-major: duplicate pixels in Y direction */
  778.      for (i=0;i<n;i++) {
  779.         if (mask[i]) {
  780.            GLint yy;
  781.            GLint y0 = y[i] + w0;
  782.            GLint y1 = y[i] + w1;
  783.            for (yy=y0;yy<=y1;yy++) {
  784.           PB_WRITE_TEX_PIXEL( x[i], yy, z[i],
  785.                  red[i], green[i], blue[i], alpha[i], s[i], t[i] );
  786.            }
  787.            PB_CHECK_FLUSH
  788.         }
  789.      }
  790.       }
  791.       else {
  792.      /* Y-major: duplicate pixels in X direction */
  793.      for (i=0;i<n;i++) {
  794.         if (mask[i]) {
  795.            GLint xx;
  796.            GLint x0 = x[i] + w0;
  797.            GLint x1 = x[i] + w1;
  798.            for (xx=x0;xx<=x1;xx++) {
  799.           PB_WRITE_TEX_PIXEL( xx, y[i], z[i],
  800.                  red[i], green[i], blue[i], alpha[i], s[i], t[i] );
  801.            }
  802.            PB_CHECK_FLUSH
  803.         }
  804.      }
  805.       }
  806.    }
  807. }
  808.  
  809.  
  810.  
  811.  
  812. /*
  813.  * Determine which line drawing function to use given the current
  814.  * rendering context.
  815.  */
  816. void gl_set_line_function( void )
  817. {
  818.    /* TODO: antialiased lines */
  819.  
  820.    if (CC.RenderMode==GL_RENDER) {
  821.       CC.LineFunc = (*DD.get_line_func)();
  822.       if (CC.LineFunc) {
  823.          /* Device driver will draw lines. */
  824.       }
  825.       else if (CC.Texture.Enabled) {
  826.      CC.LineFunc = textured_rgba_line;
  827.       }
  828.       else if (CC.Line.Width!=1.0 || CC.Line.StippleFlag || CC.Line.SmoothFlag
  829.            || CC.Texture.Enabled) {
  830.      CC.LineFunc = CC.RGBAflag ? general_rgba_line : general_ci_line;
  831.       }
  832.       else {
  833.      if (CC.Light.ShadeModel==GL_SMOOTH) {
  834.         /* Width==1, non-stippled, smooth-shaded, any raster ops */
  835.         CC.LineFunc = CC.RGBAflag ? smooth_rgba_line : smooth_ci_line;
  836.      }
  837.          else {
  838.         /* Width==1, non-stippled, flat-shaded, any raster ops */
  839.         CC.LineFunc = CC.RGBAflag ? flat_rgba_line : flat_ci_line;
  840.          }
  841.       }
  842.    }
  843.    else if (CC.RenderMode==GL_FEEDBACK) {
  844.       CC.LineFunc = feedback_line;
  845.    }
  846.    else {
  847.       /* GL_SELECT mode */
  848.       CC.LineFunc = select_line;
  849.    }
  850. }
  851.  
  852.  
  853.